<?php
/**
 * | 节程 [ 节程赋能开发者，助力企业发展 ]
 * +----------------------------------------------------------------------
 *  | Copyright (c) 2020~2029 温州惊蛰网络科技有限公司 All rights reserved.
 * +----------------------------------------------------------------------
 *  | Licensed 节程并不是自由软件，未经许可不能去掉节程相关版权
 * +----------------------------------------------------------------------
 */


namespace app\shop_admin\service;
use app\shop_admin\model\InvoiceTemplate AS template;
use app\shop_admin\model\Order;
use think\Exception;

class InvoiceService
{
    public $order;
    /**
     * @param int $page
     * @param int $size
     * @param int $merchant_id
     * @return array
     * @throws \think\db\exception\DbException
     */
    public function list(int $page, int $size, int $merchant_id) : array{
        $list = template::field('id,name,title,express_id,create_time')
            ->with(['expressName'])
            ->where('merchant_id',$merchant_id)
            ->paginate(['page' => $page,'list_rows' => $size]);
        return [HTTP_SUCCESS,$list];
    }

    /**
     * @param int $id
     * @return array
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function read(int $id){
        $find = template::with(['expressName'])->find($id);
        if (empty($find))
            throw new Exception('数据不存在',HTTP_SUCCESS);
        return [HTTP_SUCCESS,$find];
    }

    /**
     * @param string $config
     * @param string $title
     * @param string $name
     * @param int $express_id
     * @param string $logo
     * @return array
     */
    public function create(string $config, string $title, string $name, int $express_id, string $logo,int $merchant_id) : array{
        $template = template::create([
            'config' => $config,
            'title' => $title,
            'name' => $name,
            'express_id' => $express_id,
            'logo' => $logo,
            'merchant_id' => $merchant_id
        ]);
        return [HTTP_SUCCESS,$template];
    }

    /**
     * @param $id
     * @param string $config
     * @param string $title
     * @param string $name
     * @param int $express_id
     * @param string $logo
     * @return array
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function update(int $id, string $config, string $title, string $name, int $express_id, string $logo) : array{
        $template = template::find($id);
        if (empty($template))
            throw new Exception('模板不存在',HTTP_INVALID);
        $is_bool = $template->save([
            'config' => $config,
            'title' => $title,
            'name' => $name,
            'express_id' => $express_id,
            'logo' => $logo
        ]);
        return [$is_bool ? HTTP_SUCCESS : HTTP_INVALID,'更新'.($is_bool ? '成功' : '失败')];
    }

    /**
     * @param $id
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function delete(int $id) : array{
        $template = template::find($id);
        if (empty($template))
            throw new Exception(HTTP_INVALID,'模板不存在');
        $template->delete();
        return [HTTP_SUCCESS,'删除成功'];
    }

    /**
     * @param int $template_id
     * @param int|null $order_id
     * @throws Exception
     * @throws \Picqer\Barcode\Exceptions\BarcodeException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function print(int $template_id, array $order_id,array $order_commodity_id) : array{
        $template = template::find($template_id);
        $order = Order::with([
            'user',
            'orderFreight',
            'orderCommodity' => function($sql) use ($order_commodity_id){
                $sql->where('id','IN',$order_commodity_id)
                    ->with(['skuPvsValue','commodity']);
            }
        ])
            ->where('id','IN',$order_id)
            ->select();
        if (empty($order))
            throw new Exception('订单不存在',HTTP_INVALID);
        if (empty($template))
            throw new Exception('模板不存在',HTTP_INVALID);
        $content = [];
        foreach ($order AS $key => $value) {
            $data = $this->fieldArray($value, $template);
            $content[] = $this->content($template->config, $data, $template->logo);
        }
        return [HTTP_SUCCESS,$content];
    }

    /**
     * @param $config
     * @param $data
     * @param $logo
     * @return string
     */
    private function content($config, $data, $logo) : string{
        $html = file_get_contents(__CURRENT__.'/invoice.html');
        $html = str_replace('{logo}',$logo,$html);
        foreach ($config AS $index => $item){
            $expression = '/<!--start '.$index.'-->((.|\n)+?)<!--end '.$index.'-->/';
            preg_match_all($expression,$html,$match);
            if ($item['slide'] == 0){
                foreach ($match[0] AS $key => $value)
                    $html = str_replace($value,'',$html);
            }else{
                foreach ($item AS $key => $value){
                    if ($value == 0){
                        $expression = '/<!--start '.$key.'-->((.|\n)+?)<!--end '.$key.'-->/';
                        preg_match_all($expression,$html,$match);
                        if (empty($match[0]))continue;
                        foreach ($match[0] AS $field => $parameter)
                            $html = str_replace($parameter,'',$html);
                    }
                }
                $expression = '/<!--start '.$index.'-->((.|\n)+?)<!--end '.$index.'-->/';
                preg_match_all($expression,$html,$match);
                if ($index == 'goods') {
                    $string = '';
                    $expression = '/<!--start goods list-->((.|\n)+?)<!--end goods list-->/';
                    preg_match_all($expression,$html,$match);
                    foreach ($data['goods'] AS $key => $value){
                        $keys = array_keys($value);
                        $values = array_values($value);
                        foreach ($keys AS $field => $parameter)
                            $keys[$field] = '{' . $parameter . '}';
                        $string .= str_replace($keys,$values,$match[0][0]);
                    }
                    $html = str_replace($match[0][0], $string, $html);
                }else{
                    foreach ($match[0] AS $key => $value) {
                        $keys = array_keys($data[$index]);
                        $values = array_values($data[$index]);
                        foreach ($keys AS $field => $parameter)
                            $keys[$field] = '{' . $parameter . '}';
                        $string = str_replace($keys, $values, $value);
                        $html = str_replace($value, $string, $html);
                    }
                }
            }
        }
        return $html;
    }

    /**
     * @param $order
     * @param $template
     * @return array
     * @throws \Picqer\Barcode\Exceptions\BarcodeException
     */
    private function fieldArray($order, $template) : array{
        $barCode = date('YmdHis').rand(10000,99999);
        $generator = new \Picqer\Barcode\BarcodeGeneratorPNG();
        $generator = $generator->getBarcode($barCode,$generator::TYPE_CODE_128);
        $generator = 'data:image/png;base64,'.base64_encode($generator);
        $number = 0;
        $order_type = [1 => '快递',2 => '自提',3 => '同城配送'];
        foreach ($order->orderCommodity AS $key => $value){
            $number += $value->count;
        }
        $array = [
            'invoice' => [
                'title' => $template->title,
                'bar-code-image' => $generator,
                'bar-code' => $barCode,
                'time' => date('Y-m-d H:i:s')
            ],
            'fee' => [
                'amount' => ($order->money - $order->discount - $order->discount_amount),
                'number' => $number,
                'freight' => empty($order->orderFreight) ? 0 : $order->orderFreight->freight,
                'discount' => (bcadd($order->discount , $order->discount_amount + $order->discount_level_amount,2)),
                'subtotal' => $order->money
            ],
            'order' => [
                "name" => $order->user->nickname,
                "order_no" => $order->order_no,
                "pay_time" => $order->pay_time,
                "pay_type" => $order->pay_id,
                "order_type" => $order_type[$order->order_type],
                "create_time" => $order->create_time
            ],
            'receiving' => [
                "info" => $order->remake,
                "name" => $order->consignee,
                "mobile" => $order->iphone,
                "address" => str_replace(',','',$order->address)
            ],
            'goods' => $this->goods($order->orderCommodity),
            "qrcode" => [
                "bottom" => $template->config['qrcode']['bottom'],
                "qrcode" => 'data:image/png;base64,'. base64_encode(file_get_contents(qrcode($template->config['qrcode']['content'])))
            ]
        ];
        return $array;
    }

    /**
     * @param $orderCommodity
     * @return array
     */
    private function goods($orderCommodity) : array{
        $array = [];
        foreach ($orderCommodity AS $key => $value){
            $amount = $value->money;
            $after = $value->pvs_value ?? '';
            $attach_value = \think\facade\Db::name('order_commodity_attach')
                ->field('attach_value,sum(num * attach_price) AS money')
                ->where('order_id',$value['order_id'])
                ->where('group',$value['group'])
                ->select()
                ->toArray();
            if (!empty($attach_value)){
                $money = array_sum(array_column($attach_value,'money'));
                $attach_value = array_column($attach_value,'attach_value');
                $after .= '('.implode('x',$attach_value).')';
                $amount = bcadd($amount,$money,2);
            }
            $array[] = [
                "serial" => ($key + 1),
                "after" => $after,
                "name" => $value->commodity->name,
                "price" => $value->commodity->sell_price,
                "amount" => $amount,
                "number" => $value->count
            ];
        }
        return $array;
    }
}